import classNames from 'classnames';

import { isFunction } from 'min-dash';

import {
  useError,
  usePrevious,
  useShowEntryEvent
} from '../../hooks';

import {
  useEffect,
  useState
} from 'preact/hooks';

import Description from './Description';

/**
 * @typedef { { value: string, label: string, disabled: boolean, children: { value: string, label: string, disabled: boolean } } } Option
 */

/**
 * Provides basic select input.
 *
 * @param {object} props
 * @param {string} props.id
 * @param {string[]} props.path
 * @param {string} props.label
 * @param {Function} props.onChange
 * @param {Function} props.onFocus
 * @param {Function} props.onBlur
 * @param {Array<Option>} [props.options]
 * @param {string} props.value
 * @param {boolean} [props.disabled]
 */
function Radio(props) {
  const {
    id,
    label,
    onChange,
    options = [],
    value = '',
    disabled,
    onFocus,
    onBlur
  } = props;

  const ref = useShowEntryEvent(id);

  const [ localValue, setLocalValue ] = useState(value);

  const handleChangeCallback = ({ target }) => {
    onChange(target.value);
  };

  const handleChange = e => {
    handleChangeCallback(e);
    setLocalValue(e.target.value);
  };

  useEffect(() => {
    if (value === localValue) {
      return;
    }

    setLocalValue(value);
  }, [ value ]);

  return (
    <div class="bio-properties-panel-radio">
      <label for={ prefixId(id) } class="bio-properties-panel-label">
        {label}
      </label>
        {options.map((option, idx) => {

          return (
            <label>
              <input
                ref={ref}
                id={prefixId(id)}
                name={id}
                type='radio'
                className="bio-properties-panel-input"
                onInput={handleChange}
                onFocus={onFocus}
                onBlur={onBlur}
                checked={ localValue }
                value={option.value}
                disabled={disabled}
              />
                {option.label}
            </label>
          );
        })}
    </div>
  );
}

/**
 * @param {object} props
 * @param {object} props.element
 * @param {string} props.id
 * @param {string} [props.description]
 * @param {string} props.label
 * @param {Function} props.getValue
 * @param {Function} props.setValue
 * @param {Function} props.onFocus
 * @param {Function} props.onBlur
 * @param {Function} props.getOptions
 * @param {boolean} [props.disabled]
 * @param {Function} [props.validate]
 */
export default function RadioEntry(props) {
  const {
    element,
    id,
    description,
    label,
    getValue,
    setValue,
    getOptions,
    disabled,
    onFocus,
    onBlur,
    validate,
    defaultValue
  } = props;

  const options = getOptions(element);
  const [ cachedInvalidValue, setCachedInvalidValue ] = useState(null);
  const globalError = useError(id);
  const [ localError, setLocalError ] = useState(null);

  let value = getValue(element)||defaultValue;

  const previousValue = usePrevious(value);


  useEffect(() => {
    if (isFunction(validate)) {
      const newValidationError = validate(value) || null;

      setLocalError(newValidationError);
    }
  }, [ value ]);

  if (previousValue === value && localError) {
    value = cachedInvalidValue;
  }

  const error = globalError || localError;

  return (
    <div
      class={ classNames(
        'bio-properties-panel-entry',
        error ? 'has-error' : '')
      }
      data-entry-id={ id }>
      { error && <div class="bio-properties-panel-error">{ error }</div> }
      {options.map((option, idx) => {
        return (
          <label>
            <input
              id={ id }
              type='radio'
              key={ element }
              label={ label }
              value={ option.value }
              checked={ value==option.value}
              onChange={ setValue }
              onFocus={ onFocus }
              onBlur={ onBlur }
              disabled={ disabled }
            />
            {option.label}
          </label>
        );
      })}
      <Description forId={ id } element={ element } value={ description } />
    </div>
  );
}

export function isEdited(node) {
  return node && !!node.value;
}

// helpers /////////////////

function prefixId(id) {
  return `bio-properties-panel-${ id }`;
}
